package com.itheima.queue;

import java.util.Iterator;

/**
 * 仅用head，tail判断空满，head，tail需要换算成索引值
 *
 * @FileName ArrayQueue3
 * @Description
 * @Author Sword
 * @date 2025-04-09
 **/
public class ArrayQueue3<E> implements Queue<E>, Iterable<E> {

    /**
     * 求模运算
     * - 如果除数是 2 的 n 次方
     * - 那么被除数的后 n 位即为余数（模）
     * - 求被除数的后 n 位方法，与 2^n-1 按位与
     */

    private final E[] array;
    private int head = 0;
    private int tail = 0;

    public ArrayQueue3(int c) {
        //1.抛异常
        /*if ((capacity & capacity - 1) != 0) {
            throw new IllegalArgumentException("capacity 必须是 2^n");
        }*/
        //2.改成2^n   13 -> 16    22 -> 32
        c -= 1;
        c |= c >> 1;
        c |= c >> 2;
        c |= c >> 4;
        c |= c >> 8;
        c |= c >> 16;
        c += 1;
        array = (E[]) new Object[c];
    }

    @Override
    public boolean offer(E valvue) {
        if (isFull()) {
            return false;
        }
//        array[(int) (Integer.toUnsignedLong(tail) % array.length)] = valvue;
        array[tail & (array.length - 1)] = valvue;
        tail++;
        return true;
    }

    @Override
    public E poll() {
        if (isEmpty()) {
            return null;
        }
//        E value = array[(int) (Integer.toUnsignedLong(head) % array.length)];
        E value = array[head & array.length - 1];
        head++;
        return value;
    }

    @Override
    public E peek() {
        if (isEmpty()) {
            return null;
        }
//        return array[(int) (Integer.toUnsignedLong(head) % array.length)];
        return array[head & array.length - 1];
    }

    @Override
    public boolean isEmpty() {
        return tail == head;
    }

    @Override
    public boolean isFull() {
        return tail - head == array.length;
    }

    @Override
    public Iterator<E> iterator() {
        return new Iterator<E>() {
            int p = head;

            @Override
            public boolean hasNext() {
                return p != tail;
            }

            @Override
            public E next() {
//                E value = array[(int) (Integer.toUnsignedLong(p) % array.length)];
                E value = array[p & array.length - 1];
                p++;
                return value;
            }
        };
    }

    public static void main(String[] args) {

        //求离c最近，比c大的2^n(方法1)
        int c = 30;

        /*
            2^4     = 16
            2^4.?   = 30
            2^5     = 32

                (int)log2(30) + 1
            2

            log2(x) = log10(x) / log10(2)
         */
//        int n = (int) (Math.log10(c - 1) / Math.log10(2)) + 1;
//        System.out.println(n);
//        System.out.println(1 << n);

        /*
            1
            10      2^1
            100     2^2
            1000    2^3
         */

        //求离c最近，比c大的2^n(方法1)
        c -= 1;
        c |= c >> 1;
        c |= c >> 2;
        c |= c >> 4;
        c |= c >> 8;
        c |= c >> 16;
        c += 1;
        System.out.println(c);
    }
}
